package com.glsc.ngateway.platform.service.it.project;

import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.project.Project;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.project.ProjectSystemRelation;
import com.glsc.ngateway.common.api.common.dto.PageQueryParamDto;
import com.glsc.ngateway.common.api.platform.dto.it.project.ProjectDto;
import com.glsc.ngateway.common.base.converter.platform.ProjectConverter;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.it.project.ProjectRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.it.project.ProjectSystemRelationRepo;
import com.glsc.ngateway.platform.service.sequenceproduce.SequenceProducer;
import com.glsc.ngateway.platform.service.sequenceproduce.context.ProjectAddSeqContext;
import io.jsonwebtoken.lang.Collections;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author xuchang
 */
@Service
public class ProjectService {

    @Autowired
    private ProjectRepo projectRepo;

    @Autowired
    private ProjectSystemRelationRepo relationRepo;

    /**
     * 分页查询
     */
    public Page<ProjectDto> query(PageQueryParamDto<ProjectDto> param) {
        param.setParam(Objects.isNull(param.getParam()) ? new ProjectDto() : param.getParam());
        Pageable pageable = param.getPageable();
        Page<Project> pageRes = projectRepo.page(pageable, param.getParam());
        List<ProjectDto> projectDtos = ProjectConverter.do2Dto(pageRes.getContent());
        if (!Collections.isEmpty(projectDtos)) {
            //填充[关联系统]属性
            List<String> proNoList = projectDtos.stream().map(ProjectDto::getProjectNo).collect(Collectors.toList());
            // 项目关系map<项目编号， List<系统编号>>
            Map<String, List<String>> relationMap = relationRepo.findAllByProjectNoIn(proNoList).stream()
                    .collect(Collectors.groupingBy(ProjectSystemRelation::getProjectNo, Collectors.mapping(ProjectSystemRelation::getSystemClassNo, Collectors.toList())));
            projectDtos.forEach(p -> p.setSystemClassNoList(relationMap.getOrDefault(p.getProjectNo(), java.util.Collections.emptyList())));
        }
        return new PageImpl<>(projectDtos, pageable, pageRes.getTotalElements());
    }

    /**
     * 添加或修改
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(ProjectDto project) {
        if (StringUtils.isBlank(project.getProjectNo())) {
            ProjectAddSeqContext context = ProjectAddSeqContext.builder()
                    .implmentsSubject(project.getImplmentsSubject())
                    .build();
            SequenceProducer.produce(context);
            project.setProjectNo(context.getRes());
        }
        if (projectRepo.countByIdNotAndNameAndNo(project.getId(), project.getProjectName(), project.getProjectNo()) > 0) {
            throw PlatformException.error("项目编号或名称重复", false, false);
        }
        projectRepo.save(ProjectConverter.dto2Do(project));
        //处理项目-系统关系
        //原数据
        List<ProjectSystemRelation> relationsOld = relationRepo.findAllByProjectNoIn(java.util.Collections.singletonList(project.getProjectNo()));
        Map<String, ProjectSystemRelation> sysClassNoOldMap = relationsOld.stream().collect(Collectors.toMap(ProjectSystemRelation::getSystemClassNo, Function.identity()));
        //新数据
        List<ProjectSystemRelation> addRelations = new ArrayList<>();
        if (!Collections.isEmpty(project.getSystemClassNoList())) {
            project.getSystemClassNoList().add(new String("a"));
            project.getSystemClassNoList().forEach(n -> {
                //原数据没有，则新增
                if (!sysClassNoOldMap.containsKey(n)) {
                    ProjectSystemRelation rNew = new ProjectSystemRelation();
                    rNew.setProjectNo(project.getProjectNo());
                    rNew.setSystemClassNo(n);
                    addRelations.add(rNew);
                } else {
                    //原数据有则从集合中剔除
                    relationsOld.remove(sysClassNoOldMap.get(n));
                }
            });
        }
        //剩下的全是需要删除的
        if (!Collections.isEmpty(relationsOld)) {
            relationRepo.deleteAll(relationsOld);
        }
        //添加数据
        if (!Collections.isEmpty(addRelations)) {
            relationRepo.saveAll(addRelations);
        }
    }

    /**
     * 逻辑删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(@NotNull Long id) {
        Project project = projectRepo.findById(id).orElseThrow(() -> PlatformException.error("未找到记录，请重新常识", false, false));
        projectRepo.delete(project);
        relationRepo.deleteAllByProjectNo(project.getProjectNo());
    }
}
